import throttle from 'lodash/throttle'
import { defineStore } from 'pinia'
/**
 * 标签页宽度计算的组合式函数
 * 处理标签页动态宽度计算和窗口大小监听
 */
import { onMounted, onUnmounted, ref, watch } from 'vue'
import { useTabStore } from './tab'

// ==================== 常量配置 ====================
export const RIGHT_OFFSET = 250 // 右侧固定元素的宽度
export const TAB_MARGIN = 4 // 每个标签页的左右margin
export const MAX_TAB_WIDTH = 200 // 标签页最大宽度
export const GROUP_HEADER_WIDTH = 58 // 分组头部宽度
export const RIGHT_RESERVED_WIDTH = 120 // 标签页右侧预留的宽度

export const useTabWidthStore = defineStore('tab-width', () => {
  const tabStore = useTabStore()

  // ==================== 响应式状态 ====================
  const documentWidth = ref(0)
  const isMouseOver = ref(false)
  const tabWidth = ref(0)

  const dragBoundary = computed(() => {
    return {
      leftMin: tabWidth.value / 5,
      rightMin: tabWidth.value / 5
    }
  })

  // ==================== 宽度计算 ====================
  /**
   * 计算每个标签页的宽度
   * 考虑分组头部占用的空间和可见标签页数量
   */
  function calculateTabWidth(): number {
    const visibleTabsCount = tabStore.visibleTabsCount

    if (visibleTabsCount === 0) return MAX_TAB_WIDTH

    // 计算分组头部占用的总宽度
    const groupsCount = tabStore.tabs.filter(item => 'tabs' in item).length
    const totalGroupHeaderWidth = groupsCount * GROUP_HEADER_WIDTH

    // 计算总间隔宽度
    const totalMarginWidth = visibleTabsCount * TAB_MARGIN

    // 可用宽度计算
    const availableWidth =
      documentWidth.value - RIGHT_OFFSET - totalGroupHeaderWidth - totalMarginWidth
    const calculatedWidth = availableWidth / visibleTabsCount
    return Math.min(calculatedWidth, MAX_TAB_WIDTH)
  }

  // ==================== 监听器 ====================
  // 删除动画状态
  const isDeleting = ref(false)

  // 防抖计算宽度，避免频繁计算
  let debounceTimer: ReturnType<typeof setTimeout> | null = null

  const debounceCalculateWidth = throttle(() => {
    tabWidth.value = calculateTabWidth()
  }, 100)

  /**
   * 监听宽度变化并重新计算标签页宽度
   */
  watch([() => tabStore.visibleTabsCount, documentWidth, isMouseOver], (data, oldData) => {
    // 特殊情况：关闭标签页时且鼠标悬停时不更新宽度，避免闪烁
    if (
      data[0] < oldData[0] &&
      tabStore.lastClosedTabIndex !== null &&
      tabStore.lastClosedTabIndex <= tabStore.visibleTabsCount - 1 &&
      isMouseOver.value
    ) {
      return
    }

    // 如果正在删除动画中，延迟更新宽度
    if (isDeleting.value) {
      return
    }

    // 使用防抖计算宽度
    debounceCalculateWidth()
  })

  // ==================== 窗口大小监听 ====================
  const updateDocumentWidth = () => {
    documentWidth.value = document.documentElement.clientWidth - RIGHT_RESERVED_WIDTH
  }

  onMounted(() => {
    updateDocumentWidth()
    window.addEventListener('resize', updateDocumentWidth)
  })

  onUnmounted(() => {
    window.removeEventListener('resize', updateDocumentWidth)
    // 清理防抖定时器
    if (debounceTimer) {
      clearTimeout(debounceTimer)
      debounceTimer = null
    }
    // 清理容器缓存
    containerElement = null
  })

  // ==================== 鼠标事件处理 ====================
  // 缓存容器元素，避免频繁查询DOM
  let containerElement: HTMLElement | null = null

  const getContainer = () => {
    if (!containerElement) {
      containerElement = document.querySelector('.tabs-container')
    }
    return containerElement
  }

  const handleMouseOver = (event: MouseEvent) => {
    const target = event.target as HTMLElement
    const container = getContainer()
    if (container?.contains(target)) {
      isMouseOver.value = true
    }
  }

  const handleMouseOut = (event: MouseEvent) => {
    const container = getContainer()
    const relatedTarget = event.relatedTarget as HTMLElement

    // 只有当鼠标真正离开容器时才设置为false
    if (container && !container.contains(relatedTarget)) {
      isMouseOver.value = false
    }
  }

  // ==================== 导出 ====================
  return {
    // 状态
    tabWidth,
    isMouseOver,
    isDeleting,
    dragBoundary,
    // 方法
    handleMouseOver,
    handleMouseOut
  }
})
